
昨天開始記錄 Claude 執行、人工審查與返工的時間。記著記著,我心裡想的是:怎樣才算完成?
程式寫完?測試全部綠燈?需求都開發完成?
以前一行一行寫,每一段都要時間。現在 Claude Code 幾分鐘就把程式和測試交回來,那個問題反而更明顯:東西都出來了,這樣就算完成了嗎?
Day 3 那份訂單取消程式,十八個斷言全過,我卻還不能接受,因為「取消後是否要求退款」需求沒說。十八個綠燈只能說明那些測試的預期成立,不能替退款規則找到依據。
AI 可以很快把程式寫出來,卻不會讓模糊的需求自動變清楚。 沒說明的地方,也可能更快變成程式裡的決定。所以要談完成,得先知道答應交付什麼:需求說要解決什麼問題,規格把它整理成行為、限制與驗收條件,才有依據判斷做到了沒有。
Anthropic 八月的 AI-Native SDLC playbook 把這件事拆成三份版控檔:intent 保存問題與期待結果,spec 寫行為,plan 寫怎麼做。它是建議流程,不是「照做就會變快」的實證,但這個分工對我有用:「為什麼做」「要有哪些行為」「準備怎麼做」分開確認,才不會一張工單寫了功能名稱,就直接變成開發指令。
| 文件 | 要回答的問題 | 誰核對 |
|---|---|---|
intent.md |
為什麼做?要改善誰的什麼問題,怎麼看出有改善? | 能確認問題與期待結果的需求負責人 |
spec.md |
要有哪些行為、例外與驗收條件,才能回應這個目的? | RD 整理,核心規則由對應 Owner 確認 |
plan.md |
改哪些地方、怎麼實作、怎麼驗證? | 工程師核對可行性與影響範圍 |
這裡的 Why,是誰遇到什麼問題、期待什麼改變、不能犧牲哪些限制。這次我試著用 intent.md 保存它,讓 Claude Code 讀 Spec 時能回頭核對;Jira 保留正式需求與確認紀錄。規格回應不了目的,就先回頭問。
真實工作裡,我手上通常有兩樣東西:Spec 列功能與規則,Prototype 看實際操作。RD 再從系統分析與設計(SA/SD)的角度,用循序圖、流程圖與狀態圖釐清需求,確認疑問、整理測試案例,後面才進開發;改動跨系統時多一張 C4 架構圖看影響範圍。
這些圖我請 AI 用 Mermaid 畫,保留文字原始碼,核對時直接看節點與連線。看圖比讀一疊 Markdown 容易抓到重點,大家對著同一段流程討論;細節與決策理由仍留在規格裡。我依問題選圖,不是每次都畫齊;Spec 與 Prototype 不一致就回頭確認,釐清後把關鍵路徑與例外寫成驗收案例。這些材料的用途,是找出需求中的空白,確認後才變成判斷完成的依據。

作者實務整理。
接下來沿用訂單取消題目,把這條線走一小段。這次只提供文字需求與程式骨架,沒有操作原型;能檢查規則缺口,不能據此說整套需求流程已跑通。
沿用 Day 3 的訂單取消教學示範案例。情境與需求是為了示範而設計,程式、測試與 Claude Code 審查則有實際執行;其中的教學假設不代表真實業務決策。當時給 Claude Code 的功能需求只有一句,另外提供程式骨架與執行限制,中文意思是:
讓使用者可以取消尚未出貨的訂單。
很像主管在走廊上講的那一句。它已經是功能要求,卻沒有交代誰遇到什麼困難、為什麼需要取消。程式骨架另外有是否出貨、是否付款、是否取消,以及「是否要求退款」的回傳欄位;任務也明訂不連付款服務、不執行退款,退款只是一個記憶體旗標。
三種資訊要分開看:需求說想要的行為,骨架說目前有哪些欄位,限制說這個示範能做什麼。有退款欄位,不代表取消時就應該把它設成 true。 把需求明說的取消路徑與未決問題分開畫,就看得見這組空白:

作者依示範需求與骨架重繪,非模型輸出;實線只摘要原句允許的取消行為。
我也讓 Claude Code 畫一次看看。給它同一份 spec.md,工具只留 Read(--tools Read --allowedTools Read),這輪不提供模型改檔工具,要它用 Mermaid 畫出需求明說的轉換並標來源,把沒有依據的轉換另列、註明該找誰確認(2 回合、12.6 秒、費用估值 US$0.04)。
它列出的三個待確認,與上圖相同:已付款是否要求退款、已出貨呼叫取消該回什麼、重複取消是否保持相同結果。
但它多畫了一條「Placed → Shipped:出貨」,超出原句明示的範圍;取消邊沒有照要求標來源;待確認被塞進圖內註記,沒有逐條列起訖狀態與確認角色。找到問題,不代表整張圖就能接受。 RD 要把每條轉換對回原文,移除或另列沒有依據的推論,再把退款與例外交給 Owner。
以訂單題目來說,可以先整理成這份 intent.md;原題沒有提供的 Why,保留待確認:
# 訂單取消的目的
狀態:待需求負責人確認
來源:教學示範題目「讓使用者可以取消尚未出貨的訂單」
## 誰遇到什麼問題
待確認:誰需要取消?目前怎麼處理,又卡在哪裡?
## 期待結果與觀察方式
待確認:希望改善什麼?用什麼資料比較改善前後?
「做出取消功能」是交付內容,還不是改善結果。
## 已知範圍與限制
- 功能要求:取消尚未出貨的訂單。
- 本次示範限制:不連付款服務、不執行退款。
## 尚待決定
- 取消與退款的責任分界。
- 哪個角色確認目的、範圍與期待結果?
這份草稿的價值,是讓不知道的地方有位置可放。不能因為檔名叫 intent,就讓 Claude 替使用者編一個看似合理的痛點。真實工作裡,要從需求訪談或 Jira 補入已確認的答案、來源版本與確認人。
自己試時,先建一個練習資料夾,把上面的草稿存成 intent.md,再把你有權使用的需求原文存成 spec.md,保留來源版本。開啟已安裝並登入的 Claude Code,工作目錄指向這個資料夾,再貼下面的提示。這一步不必先準備程式;想對照同一題,可用配套 repo 的 days/day06/lab/intent/ 材料。
先讀取 intent.md 與 spec.md,不修改程式。
列出你實際讀取的檔案與文件內記載的來源版本;未記載就標未知。
用自己的話重述:誰遇到什麼問題、期待什麼結果、有哪些限制。
將 Spec 的主要行為對回這些目的,指出沒有依據或互相衝突的地方。
intent 中的待確認項目不要補答案,列出需要向人確認的問題。
先交回核對結果,等我確認;這一步不產生實作。
交回來後,先核對三件事:讀到的是否就是這兩份材料、待確認的答案是否被自行補上、每個衝突能否指出來源。少一件就把缺件寫回去,不進實作;這就是這個小練習的完成條件。互動操作與下面保存的 CLI 實跑設定不同,不要求結果逐字一致。
我用這段提示實跑了一次(同樣只留 Read,3 回合、15.5 秒、費用估值 US$0.04)。--output-format stream-json 的 trace 顯示它讀了兩個檔;它沒有替待確認的四項補答案,把主要落差說成一句:「spec 把 RefundRequested 寫進簽名,等於替尚未確認的目的做了技術決策」。 然後列了三個要向人確認的問題,與狀態圖的三個空白相同。提示要求列來源版本、未記載標未知,它也漏了。
但我不接受它對簽名的那個推論:介面有退款欄位,不等於退款的觸發條件已經決定。 它找到值得問的問題,卻把欄位與規則混在一起;讀過兩份文件,仍要核對它怎麼理解。
檔名放在 repo 裡,它會不會自己讀?我另外試了一次:另一個資料夾放相同的兩份材料,提示只說「整理一份驗收草稿」,不提任何檔名(5 回合、24 秒、費用估值 US$0.03)。trace 留下四次 Read:資料夾路徑讀取失敗、README.md 不存在,spec.md 與 SPEC.md 則讀到同一份內容。它交回六題驗收草稿,卻沒有讀取 intent.md,也沒有處理目的。這次提示和前一次不同,不能據此算出指名檔案的改善率。
我帶走的做法很簡單:重要材料在提示裡點名,再查 trace 的 Read 與回傳內容;不假設檔案放進 repo 就一定被讀到。
目的與範圍確認後,才適合把規格整理成可接受的交付條件。下面回到另一個獨立實跑:只用既有 spec.md 找規則缺口,沒有接上前面的 intent 核對,也沒有取得真實需求方的批准。spec.md 是示例檔名,請換成真正的需求檔;用 Jira 的話,先提供有權使用的需求內容與版本,不假設 Claude 已經能讀到工單。
先閱讀 spec.md,不修改程式,也不先替需求補答案。
請整理一份驗收草稿,每項包含:
1. 需求來源:版本、章節或原句。
2. 已明示的行為,以及對應的具體情境。
3. 尚未明示、但會改變實作或驗收結果的問題。
4. 建議由哪個角色確認;無法判定就標待指定。
5. 確認後可用什麼方式驗證。
把「需求明示」「你的推論」「待確認」分開。
來源衝突時列出兩邊,不自行選一邊。
遇到影響本次交付的未決規則,指出受阻範圍與待補決定。
先交回草稿,等確認後再實作。
這次把 Day 3 的需求、骨架與限制寫成 spec.md,讓 Claude Code 只讀材料(4 回合、39 秒、費用估值 US$0.06)。它交回一條明示行為「尚未出貨可以取消」,以及五個待確認問題:
RefundRequested 設為 true?前三題正是說明圖上的三個空白;後兩題圖上沒有,是它多想到的。它把「付款狀態可能影響退款」標成推論,沒有直接當規則,也判斷前兩題會阻擋核心實作。
我接受的是它把空白攤出來,不是它的排序:重複取消能不能稍後處理,要看本輪程式會不會接到這種輸入。 既有規範能回答的由 RD 查,退款責任這類核心決定找 Owner。
草稿本身也要核對。另一次獨立的唯讀實驗,先讓它從縮寫 spec 列問題,再開新 session 帶入草稿與局部退款決策,請它修訂驗收案例。它依決策改了案例,卻在變更表把「已付款」誤寫成「未付款」。格式完整,不能取代內容核對。
「取消後處理退款」仍然不夠具體。我會把問題縮成一筆訂單:
這筆訂單已付款、還沒出貨,也尚未取消。使用者按下取消後,本功能是否要回傳 RefundRequested = true?如果不由這裡決定,由哪個流程負責?
這樣 Owner 要回答的是行為與責任,不是評價 Claude 寫得好不好。
為了展示後面的寫法,以下是一條教學用的假設決策:取消功能只改取消狀態,退款交由另一個流程決定,本功能不提出退款要求。 真實工作裡換成 Owner 實際確認的答案與來源。
來源:教學決策 DEMO-DECISION-01(假設,非公司規則)
案例:已付款、未出貨、尚未取消的訂單
Given 訂單 Paid = true、Shipped = false、Cancelled = false
When 使用者取消訂單
Then Cancelled = true
And RefundRequested = false
And 不呼叫付款或退款服務
這時再回看 Day 3 的 refundRequested = order.Paid:對這筆已付款訂單,原實作回傳 true,示例決策要求 false。差別不在多寫一個斷言,而是預期終於有了來源;Owner 若選另一條規則,案例跟著改,不能為了讓測試繼續綠燈反過來改需求。這個案例只處理被圈定的行為,已出貨、重複取消仍待確認。
接下來才把已確認的規則、案例與適用範圍交給 Claude Code 實作。這次的提示只有五句:依已確認的驗收條件實作、逐項標出來源;為可自動驗證的條件加測試、不改預期結果;尚未確認的行為列出受阻範圍、不宣稱完成;能執行就附實際結果;交付時整理驗收條件、修改位置、驗證方式與未決事項。全文在原件 impl/prompt.txt。
進入實作前,用 decisions.md 整理依據,避免把退款答案擴大解讀:
交給 Claude 的材料是 spec.md、這份決策,以及只有簽名、方法內丟 NotImplementedException 的 Cancel 骨架。這次的 --tools 與 --allowedTools 都包含 Read、Grep、Glob、Write、Edit、Bash,才提供寫檔與執行 dotnet 的工具(12 回合、57 秒、費用估值 US$0.15)。
其他四次模型實跑未提供寫入工具:畫圖、intent 核對與不指名實驗只用 Read,驗收草稿還提供 Grep、Glob。runner 保存輸出是另一件事,不代表模型可以改程式。
它產生程式與三個測試,未出貨取消、已出貨維持原狀、已付款取消不要求退款,三項都 PASS,dotnet run 回傳 0。
但我往下讀程式,看到另一件事。下面摘自它交回的實作,省略註解:
if (order.Shipped)
{
return new CancellationResult(order, RefundRequested: false);
}
var cancelledOrder = order with { Cancelled = true };
return new CancellationResult(cancelledOrder, RefundRequested: false);
第一個分支只擋已出貨。只要未出貨,程式就把取消狀態設成 true,回傳不要求退款;中間沒有先判斷 order.Cancelled。我另外寫了一支只印結果的小程式,把一筆已取消、未出貨的訂單丟進它交回的函式:
INPUT Shipped=False Paid=True Cancelled=True
OUTPUT Cancelled=True RefundRequested=False threw=false
重複取消的規則還沒定,程式卻已經選了一種回應。 這不表示回傳相同結果一定錯;它可能正是人確認後會採用的冪等行為,只是目前沒有這個決定的依據。Claude 在註解寫著「未確認行為」,也沒替它寫測試,卻讓這個輸入走完函式。

左側為保存的測試結果;右側那條路徑另以觀察用程式執行過,不在三個測試內。
註解不是阻擋機制。 我承認那三個案例有通過的紀錄,但不接受整個取消功能。補件要求是:請 Owner 決定重複取消的預期,或明確限縮本次交付並提供呼叫端能守住範圍的依據,再補相應驗證。不能由我或 Claude 隨意補一個例外,就說問題解決了。
我會用同一張對照表追到交付,不再另外做一份只有「全部通過」的摘要:
| 驗收條件 | 規則來源 | 驗證方式 | 目前狀態 |
|---|---|---|---|
| 上述情境取消後不提出退款要求 | DEMO-DECISION-01,教學假設 | 對照取消狀態與退款旗標的測試 | 實跑 PASS(含另兩條已確認條件,三項全過) |
| 不呼叫付款或退款服務 | 原示範任務的限制 | 核對呼叫路徑與依賴 | 程式無外部呼叫;未加自動驗證 |
| 已取消訂單的重複操作 | 原需求沒有完整定義 | 先確認規則,再訂案例 | 待確認;觀察執行證實會回傳結果,不能接受此範圍 |
實際工作時,把示例換成需求版本、確認紀錄、程式版本與執行結果,Reviewer 沿著一條條件往回查,不用猜作者心裡的「完成」。這裡有兩種判斷:Spec 是否回應原本的問題,實作是否符合 Spec。這次檢查的是後者;三個測試通過,沒有回答使用者的處境是否改善。
對這次交付來說,完成是:範圍約定清楚、關鍵規則有確認依據、相應驗證有結果,剩餘問題也有明確處置。 所以這次還不能接受整個取消功能:重複取消的預期未定,程式卻已經給出結果。我要核對四件事:
這也把 Day 5 的紀錄終點說清楚:Reviewer 核對本輪材料、留下接受或退件理由與時間,一輪審查就記為完成;退件不代表這段人工投入沒發生。審查完成、功能被接受、使用後問題改善,是三件不同的事。 量測時把「因需求未定而補件」單獨標記,下一輪規則先確認後有沒有少,用 Day 5 的尺看。
我們使用 Jira,不必為了這個做法把需求管理全部搬家。可以先挑一張正在做的工單:
intent.md;spec.md 保存對應行為與驗收條件。兩份都附工單編號、來源版本與擷取時間,連同有權使用的 Prototype 操作說明交給 Claude。intent.md 與 spec.md,先看目的與功能是否對得上,再視需要整理互動或狀態;狀態轉換用狀態圖看,跨服務互動用循序圖看,未決問題列進工單。核心規則找對應 Owner;確認結果回寫 Jira,保留未決範圍。plan.md,由工程師核對;交付時用前面的表把規則、程式與結果接起來。實作發現新問題,記下原本要求、改了什麼、誰確認,再更新規格與測試。這次能不能接受,終於有了可以逐項核對的依據。接下來要留下的,是這些決定的理由:換一個任務、換一個接手的人,還能知道當時為什麼這樣約定。
參考資料:
本文實作說明
訂單取消為教學示範案例,程式、測試與 Claude Code 審查皆有實際執行。文中回合、時間與費用取自保存的執行紀錄,費用為 CLI 估值,不代表省時成效;測試通過不代表未確認的業務規則已被接受。退款決策中的教學假設,也不是真實業務批准。
配套 repo:days/day06/lab(diagram、intent、noname、draft、impl、impl-check 六個目錄)、lab-two-stage(兩階段唯讀驗證)。
方法參考
intent.md → spec.md → plan.md 三份版控產物與簽核分工。本文借用其做法,尚未完成整條流程;官方建議不等於本文已驗證的結果。intent.md。